home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / FS / STAT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-17  |  6.0 KB  |  283 lines

  1. /*
  2.  *  linux/fs/stat.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. #include <linux/mm.h>
  8. #include <linux/errno.h>
  9. #include <linux/file.h>
  10. #include <linux/smp_lock.h>
  11.  
  12. #include <asm/uaccess.h>
  13.  
  14. /*
  15.  * Revalidate the inode. This is required for proper NFS attribute caching.
  16.  */
  17. static __inline__ int
  18. do_revalidate(struct dentry *dentry)
  19. {
  20.     struct inode * inode = dentry->d_inode;
  21.     if (inode->i_op && inode->i_op->revalidate)
  22.         return inode->i_op->revalidate(dentry);
  23.     return 0;
  24. }
  25.  
  26.  
  27. #if !defined(__alpha__) && !defined(__sparc__)
  28.  
  29. /*
  30.  * For backward compatibility?  Maybe this should be moved
  31.  * into arch/i386 instead?
  32.  */
  33. static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
  34. {
  35.     static int warncount = 5;
  36.     struct __old_kernel_stat tmp;
  37.  
  38.     if (warncount) {
  39.         warncount--;
  40.         printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
  41.             current->comm);
  42.     }
  43.  
  44.     tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  45.     tmp.st_ino = inode->i_ino;
  46.     tmp.st_mode = inode->i_mode;
  47.     tmp.st_nlink = inode->i_nlink;
  48.     tmp.st_uid = inode->i_uid;
  49.     tmp.st_gid = inode->i_gid;
  50.     tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  51.     tmp.st_size = inode->i_size;
  52.     tmp.st_atime = inode->i_atime;
  53.     tmp.st_mtime = inode->i_mtime;
  54.     tmp.st_ctime = inode->i_ctime;
  55.     return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  56. }
  57.  
  58. #endif
  59.  
  60. static int cp_new_stat(struct inode * inode, struct stat * statbuf)
  61. {
  62.     struct stat tmp;
  63.     unsigned int blocks, indirect;
  64.  
  65.     memset(&tmp, 0, sizeof(tmp));
  66.     tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  67.     tmp.st_ino = inode->i_ino;
  68.     tmp.st_mode = inode->i_mode;
  69.     tmp.st_nlink = inode->i_nlink;
  70.     tmp.st_uid = inode->i_uid;
  71.     tmp.st_gid = inode->i_gid;
  72.     tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  73.     tmp.st_size = inode->i_size;
  74.     tmp.st_atime = inode->i_atime;
  75.     tmp.st_mtime = inode->i_mtime;
  76.     tmp.st_ctime = inode->i_ctime;
  77. /*
  78.  * st_blocks and st_blksize are approximated with a simple algorithm if
  79.  * they aren't supported directly by the filesystem. The minix and msdos
  80.  * filesystems don't keep track of blocks, so they would either have to
  81.  * be counted explicitly (by delving into the file itself), or by using
  82.  * this simple algorithm to get a reasonable (although not 100% accurate)
  83.  * value.
  84.  */
  85.  
  86. /*
  87.  * Use minix fs values for the number of direct and indirect blocks.  The
  88.  * count is now exact for the minix fs except that it counts zero blocks.
  89.  * Everything is in units of BLOCK_SIZE until the assignment to
  90.  * tmp.st_blksize.
  91.  */
  92. #define D_B   7
  93. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  94.  
  95.     if (!inode->i_blksize) {
  96.         blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  97.         if (blocks > D_B) {
  98.             indirect = (blocks - D_B + I_B - 1) / I_B;
  99.             blocks += indirect;
  100.             if (indirect > 1) {
  101.                 indirect = (indirect - 1 + I_B - 1) / I_B;
  102.                 blocks += indirect;
  103.                 if (indirect > 1)
  104.                     blocks++;
  105.             }
  106.         }
  107.         tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  108.         tmp.st_blksize = BLOCK_SIZE;
  109.     } else {
  110.         tmp.st_blocks = inode->i_blocks;
  111.         tmp.st_blksize = inode->i_blksize;
  112.     }
  113.     return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  114. }
  115.  
  116.  
  117. #if !defined(__alpha__) && !defined(__sparc__)
  118. /*
  119.  * For backward compatibility?  Maybe this should be moved
  120.  * into arch/i386 instead?
  121.  */
  122. asmlinkage int sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  123. {
  124.     struct dentry * dentry;
  125.     int error;
  126.  
  127.     lock_kernel();
  128.     dentry = namei(filename);
  129.  
  130.     error = PTR_ERR(dentry);
  131.     if (!IS_ERR(dentry)) {
  132.         error = do_revalidate(dentry);
  133.         if (!error)
  134.             error = cp_old_stat(dentry->d_inode, statbuf);
  135.  
  136.         dput(dentry);
  137.     }
  138.     unlock_kernel();
  139.     return error;
  140. }
  141. #endif
  142.  
  143. asmlinkage int sys_newstat(char * filename, struct stat * statbuf)
  144. {
  145.     struct dentry * dentry;
  146.     int error;
  147.  
  148.     lock_kernel();
  149.     dentry = namei(filename);
  150.  
  151.     error = PTR_ERR(dentry);
  152.     if (!IS_ERR(dentry)) {
  153.         error = do_revalidate(dentry);
  154.         if (!error)
  155.             error = cp_new_stat(dentry->d_inode, statbuf);
  156.  
  157.         dput(dentry);
  158.     }
  159.     unlock_kernel();
  160.     return error;
  161. }
  162.  
  163. #if !defined(__alpha__) && !defined(__sparc__)
  164.  
  165. /*
  166.  * For backward compatibility?  Maybe this should be moved
  167.  * into arch/i386 instead?
  168.  */
  169. asmlinkage int sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  170. {
  171.     struct dentry * dentry;
  172.     int error;
  173.  
  174.     lock_kernel();
  175.     dentry = lnamei(filename);
  176.  
  177.     error = PTR_ERR(dentry);
  178.     if (!IS_ERR(dentry)) {
  179.         error = do_revalidate(dentry);
  180.         if (!error)
  181.             error = cp_old_stat(dentry->d_inode, statbuf);
  182.  
  183.         dput(dentry);
  184.     }
  185.     unlock_kernel();
  186.     return error;
  187. }
  188.  
  189. #endif
  190.  
  191. asmlinkage int sys_newlstat(char * filename, struct stat * statbuf)
  192. {
  193.     struct dentry * dentry;
  194.     int error;
  195.  
  196.     lock_kernel();
  197.     dentry = lnamei(filename);
  198.  
  199.     error = PTR_ERR(dentry);
  200.     if (!IS_ERR(dentry)) {
  201.         error = do_revalidate(dentry);
  202.         if (!error)
  203.             error = cp_new_stat(dentry->d_inode, statbuf);
  204.  
  205.         dput(dentry);
  206.     }
  207.     unlock_kernel();
  208.     return error;
  209. }
  210.  
  211. #if !defined(__alpha__) && !defined(__sparc__)
  212.  
  213. /*
  214.  * For backward compatibility?  Maybe this should be moved
  215.  * into arch/i386 instead?
  216.  */
  217. asmlinkage int sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
  218. {
  219.     struct file * f;
  220.     int err = -EBADF;
  221.  
  222.     lock_kernel();
  223.     f = fget(fd);
  224.     if (f) {
  225.         struct dentry * dentry = f->f_dentry;
  226.  
  227.         err = do_revalidate(dentry);
  228.         if (!err)
  229.             err = cp_old_stat(dentry->d_inode, statbuf);
  230.         fput(f);
  231.     }
  232.     unlock_kernel();
  233.     return err;
  234. }
  235.  
  236. #endif
  237.  
  238. asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf)
  239. {
  240.     struct file * f;
  241.     int err = -EBADF;
  242.  
  243.     lock_kernel();
  244.     f = fget(fd);
  245.     if (f) {
  246.         struct dentry * dentry = f->f_dentry;
  247.  
  248.         err = do_revalidate(dentry);
  249.         if (!err)
  250.             err = cp_new_stat(dentry->d_inode, statbuf);
  251.         fput(f);
  252.     }
  253.     unlock_kernel();
  254.     return err;
  255. }
  256.  
  257. asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
  258. {
  259.     struct dentry * dentry;
  260.     int error;
  261.  
  262.     if (bufsiz <= 0)
  263.         return -EINVAL;
  264.  
  265.     lock_kernel();
  266.     dentry = lnamei(path);
  267.  
  268.     error = PTR_ERR(dentry);
  269.     if (!IS_ERR(dentry)) {
  270.         struct inode * inode = dentry->d_inode;
  271.  
  272.         error = -EINVAL;
  273.         if (inode->i_op && inode->i_op->readlink &&
  274.             !(error = do_revalidate(dentry))) {
  275.             UPDATE_ATIME(inode);
  276.             error = inode->i_op->readlink(dentry, buf, bufsiz);
  277.         }
  278.         dput(dentry);
  279.     }
  280.     unlock_kernel();
  281.     return error;
  282. }
  283.